home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mint108s.zoo / fasttext.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-25  |  26.1 KB  |  1,383 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith.
  3. Copyright 1992,1993 Atari Corporation.
  4. All rights reserved.
  5. */
  6.  
  7. #include "mint.h"
  8. #include "fasttext.h"
  9.  
  10. #ifdef FASTTEXT
  11.  
  12. #ifdef __GNUC__
  13. #define INLINE inline
  14. #define ITYPE long    /* gcc's optimizer likes 32 bit integers */
  15. #else
  16. #define INLINE
  17. #define ITYPE int
  18. #endif
  19.  
  20. #define CONDEV    (2)
  21.  
  22. static SCREEN *current;
  23.  
  24. static void paint P_((SCREEN *, int, char *)),
  25.      paint8c P_((SCREEN *, int, char *)),
  26.      paint816m P_((SCREEN *, int, char *));
  27.  
  28. INLINE static void curs_off P_((SCREEN *)), curs_on P_((SCREEN *));
  29. INLINE static void flash P_((SCREEN *));
  30. static void normal_putch P_((SCREEN *, int));
  31. static void escy_putch P_((SCREEN *, int));
  32. static void quote_putch P_((SCREEN *, int));
  33.  
  34. static    char *chartab[256];
  35.  
  36. #define MAX_PLANES 8
  37. static int fgmask[MAX_PLANES], bgmask[MAX_PLANES];
  38.  
  39. static long scrnsize;
  40.  
  41. short hardscroll;
  42. static char *hardbase, *oldbase;
  43.  
  44. typedef void (*Vfunc) P_((SCREEN *, int));
  45.  
  46. #define base *((char **)0x44eL)
  47. #define escy1 *((short *)0x4acL)
  48.  
  49. static Vfunc state;
  50.  
  51. static short hardline;
  52. static void (*vpaint) P_((SCREEN *, int, char *));
  53. static char *rowoff;
  54.  
  55. void init P_((void));
  56. void hardware_scroll P_((SCREEN *));
  57. INLINE static char *PLACE P_((SCREEN *, int, int));
  58. INLINE static void gotoxy P_((SCREEN *, int, int));
  59. INLINE static void clrline P_((SCREEN *, int));
  60. INLINE static void clear P_((SCREEN *));
  61. INLINE static void clrchar P_((SCREEN *, int, int));
  62. INLINE static void clrfrom P_((SCREEN *, int, int, int, int));
  63. INLINE static void delete_line P_((SCREEN *, int));
  64. INLINE static void insert_line P_((SCREEN *, int));
  65. static void setbgcol P_((SCREEN *, int));
  66. static void setfgcol P_((SCREEN *, int));
  67. static void setcurs P_((SCREEN *, int));
  68. static void putesc P_((SCREEN *, int));
  69. static void escy1_putch P_((SCREEN *, int));
  70. INLINE static void put_ch P_((SCREEN *, int));
  71.  
  72. /* routines for flashing the cursor for screen v */
  73. /* flash(v): invert the character currently under the cursor */
  74.  
  75. INLINE static void
  76. flash(v)
  77.     SCREEN *v;
  78. {
  79.     char *place;
  80.     ITYPE i, j, vplanes;
  81.  
  82.     vplanes = v->planes + v->planes;
  83.     place = v->cursaddr;
  84.  
  85.     for (j = v->cheight; j > 0; --j) {
  86.         for (i = 0; i < vplanes; i+=2)
  87.             place[i] = ~place[i];
  88.  
  89.         place += v->planesiz;
  90.     }
  91.     v->curstimer = v->period;
  92. }
  93.  
  94. /* make sure the cursor is off */
  95.  
  96. INLINE
  97. static void
  98. curs_off(v)
  99.     SCREEN *v;
  100. {
  101.     if (v->flags & CURS_ON) {
  102.         if (v->flags & CURS_FSTATE) {
  103.             flash(v);
  104.             v->flags &= ~CURS_FSTATE;
  105.         }
  106.     }
  107. }
  108.  
  109. /* OK, show the cursor again (if appropriate) */
  110.  
  111. INLINE static void
  112. curs_on(v)
  113.     SCREEN *v;
  114. {
  115.     if (v->hidecnt) return;
  116.  
  117.     if (v->flags & CURS_ON) {
  118. #if 0
  119.     /* if the cursor is flashing, we cheat a little and leave it off
  120.      * to be turned on again (if necessary) by the VBL routine
  121.      */
  122.         if (v->flags & CURS_FLASH) {
  123.             v->curstimer = 2;
  124.             return;
  125.         }
  126. #endif
  127.         if (!(v->flags & CURS_FSTATE)) {
  128.             v->flags |= CURS_FSTATE;
  129.             flash(v);
  130.         }
  131.     }
  132. }
  133.  
  134. void
  135. init()
  136. {
  137.     SCREEN *v;
  138.     int i, j;
  139.     char *data, *foo;
  140.     static char chardata[256*16];
  141.     register int linelen;
  142.  
  143.     foo = lineA0();
  144.     v = (SCREEN *)(foo - 346);
  145.     
  146.     /* Ehem... The screen might be bigger than 32767 bytes.
  147.        Let's do some casting... 
  148.        Erling
  149.     */
  150.     linelen = v->linelen;
  151.     scrnsize = (v->maxy+1)*(long)linelen;
  152.     rowoff = (char *)kmalloc((long)((v->maxy+1) * sizeof(long)));
  153.     if (rowoff == 0) {
  154.         FATAL("Insufficient memory for screen offset table!");
  155.     } else {
  156.         long off, *lptr = (long *)rowoff;
  157.         for (i=0, off=0; i<=v->maxy; i++) {
  158.             *lptr++ = off;
  159.             off += linelen;
  160.         }
  161.     }
  162.     if (hardscroll == -1) {
  163.     /* request for auto-setting */
  164.         hardscroll = v->maxy+1;
  165.     }
  166.     if (hardscroll > 0) {
  167.         if (!hardbase)
  168.             hardbase = (char *)(((long)kcore(SCNSIZE(v)+256L)+255L)
  169.                        & 0xffffff00L);
  170.  
  171.         if (hardbase == 0) {
  172.             ALERT("Insufficient memory for hardware scrolling!");
  173.         } else {
  174.             quickmove(hardbase, base, scrnsize);
  175.             v->cursaddr = v->cursaddr + (hardbase - base);
  176.             oldbase = base;
  177.             base = hardbase;
  178.             Setscreen(hardbase, hardbase, -1);
  179.         }
  180.     }
  181.     hardline = 0;
  182.     if (v->cheight == 8 && v->planes == 2) {
  183.         foo = &chardata[0];
  184.         vpaint = paint8c;
  185.         for (i = 0; i < 256; i++) {
  186.             chartab[i] = foo;
  187.             data = v->fontdata + i;
  188.             for (j = 0; j < 8; j++) {
  189.                 *foo++ = *data;
  190.                 data += v->form_width;
  191.             }
  192.         }
  193.     } else if ((v->cheight == 16 || v->cheight == 8) && v->planes == 1) {
  194.         foo = &chardata[0];
  195.         vpaint = paint816m;
  196.         for (i = 0; i < 256; i++) {
  197.             chartab[i] = foo;
  198.             data = v->fontdata + i;
  199.             for (j = 0; j < v->cheight; j++) {
  200.                 *foo++ = *data;
  201.                 data += v->form_width;
  202.             }
  203.         }
  204.     }
  205.     else
  206.         vpaint = paint;
  207.  
  208.     if (v->hidecnt == 0) {
  209.     /*
  210.      * make sure the cursor is set up correctly and turned on
  211.      */
  212.         (void)Cursconf(0,0);    /* turn cursor off */
  213.  
  214.         v->flags &= ~CURS_FSTATE;
  215.  
  216.     /* now turn the cursor on the way we like it */
  217.         v->hidecnt = 0;
  218.         curs_on(v);
  219.     } else {
  220.         (void)Cursconf(0,0);
  221.         v->flags &= ~CURS_ON;
  222.         v->hidecnt = 1;
  223.     }
  224.  
  225.     current = v;
  226.     /* setup bgmask and fgmask */
  227.     setbgcol(v, v->bgcol);
  228.     setfgcol(v, v->fgcol);
  229.     state = normal_putch;
  230. }
  231.  
  232. /*
  233.  * PLACE(v, x, y): the address corresponding to the upper left hand corner of
  234.  * the character at position (x,y) on screen v
  235.  */
  236. INLINE static
  237. char *PLACE(v, x, y)
  238.     SCREEN *v;
  239.     int x, y;
  240. {
  241.     char *place;
  242.     int i, j;
  243.  
  244.     place = base + x;
  245.     if (y == v->maxy)
  246.         place += scrnsize - v->linelen;
  247.     else if (y) {
  248.         y+=y;    /* Make Y into index for longword array. */
  249.         y+=y;    /* Two word-size adds are faster than a 2-bit shift. */
  250.         place += *(long *)(rowoff + y);
  251.     }
  252.     if ((j = v->planes-1)) {
  253.         i = (x & 0xfffe);
  254.         do place += i;
  255.         while (--j);
  256.     }
  257.     return place;
  258. }
  259.  
  260. /*
  261.  * paint(v, c, place): put character 'c' at position 'place' on screen
  262.  * v. It is assumed that x, y are proper coordinates!
  263.  * Specialized versions (paint8c and paint816m) of this routine follow;
  264.  * they assume 8 line high characters, medium res. and 8 or 16 line/mono,
  265.  * respectively.
  266.  */
  267.  
  268. static void
  269. paint(v, c, place)
  270.     SCREEN *v;
  271.     int c;
  272.     char *place;
  273. {
  274.     char *data, d, doinverse;
  275.     ITYPE j, planecount;
  276.     int vplanes;
  277.     long vform_width, vplanesiz;
  278.  
  279.     vplanes = v->planes;
  280.  
  281.     data = v->fontdata + c;
  282.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  283.     vform_width = v->form_width;
  284.     vplanesiz = v->planesiz;
  285.  
  286.     for (j = v->cheight; j > 0; --j) {
  287.         d = *data ^ doinverse;
  288.         for (planecount = 0; planecount < vplanes; planecount++)
  289.           place[planecount << 1]
  290.             = ((d & (char) fgmask[planecount])
  291.                | (~d & (char) bgmask[planecount]));
  292.         place += vplanesiz;
  293.         data += vform_width;
  294.     }
  295. }
  296.  
  297. static void
  298. paint8c(v, c, place)
  299.     SCREEN *v;
  300.     int c;
  301.     char *place;
  302. {
  303.     char *data;
  304.     char d, doinverse;
  305.     char bg0, bg1, fg0, fg1;
  306.     long vplanesiz;
  307.  
  308.     data = chartab[c];
  309.  
  310.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  311.     vplanesiz = v->planesiz;
  312.     bg0 = bgmask[0];
  313.     bg1 = bgmask[1];
  314.     fg0 = fgmask[0];
  315.     fg1 = fgmask[1];
  316.  
  317.     if (!doinverse && !bg0 && !bg1 && fg0 && fg1) {
  318.         /* line 1 */
  319.         d = *data++;
  320.         *place = d;
  321.         place[2] = d;
  322.         place += vplanesiz;
  323.  
  324.         /* line 2 */
  325.         d = *data++;
  326.         *place = d;
  327.         place[2] = d;
  328.         place += vplanesiz;
  329.  
  330.         /* line 3 */
  331.         d = *data++;
  332.         *place = d;
  333.         place[2] = d;
  334.         place += vplanesiz;
  335.  
  336.         /* line 4 */
  337.         d = *data++;
  338.         *place = d;
  339.         place[2] = d;
  340.         place += vplanesiz;
  341.  
  342.         /* line 5 */
  343.         d = *data++;
  344.         *place = d;
  345.         place[2] = d;
  346.         place += vplanesiz;
  347.  
  348.         /* line 6 */
  349.         d = *data++;
  350.         *place = d;
  351.         place[2] = d;
  352.         place += vplanesiz;
  353.  
  354.         /* line 7 */
  355.         d = *data++;
  356.         *place = d;
  357.         place[2] = d;
  358.         place += vplanesiz;
  359.  
  360.         /* line 8 */
  361.         d = *data;
  362.         *place = d;
  363.         place[2] = d;
  364.     } else {
  365.         /* line 1 */
  366.         d = *data++ ^ doinverse;
  367.         *place = ((d & fg0) | (~d & bg0));
  368.         place[2] = ((d & fg1) | (~d & bg1));
  369.         place += vplanesiz;
  370.  
  371.         /* line 2 */
  372.         d = *data++ ^ doinverse;
  373.         *place = ((d & fg0) | (~d & bg0));
  374.         place[2] = ((d & fg1) | (~d & bg1));
  375.         place += vplanesiz;
  376.  
  377.         /* line 3 */
  378.         d = *data++ ^ doinverse;
  379.         *place = ((d & fg0) | (~d & bg0));
  380.         place[2] = ((d & fg1) | (~d & bg1));
  381.         place += vplanesiz;
  382.  
  383.         /* line 4 */
  384.         d = *data++ ^ doinverse;
  385.         *place = ((d & fg0) | (~d & bg0));
  386.         place[2] = ((d & fg1) | (~d & bg1));
  387.         place += vplanesiz;
  388.  
  389.         /* line 5 */
  390.         d = *data++ ^ doinverse;
  391.         *place = ((d & fg0) | (~d & bg0));
  392.         place[2] = ((d & fg1) | (~d & bg1));
  393.         place += vplanesiz;
  394.  
  395.         /* line 6 */
  396.         d = *data++ ^ doinverse;
  397.         *place = ((d & fg0) | (~d & bg0));
  398.         place[2] = ((d & fg1) | (~d & bg1));
  399.         place += vplanesiz;
  400.  
  401.         /* line 7 */
  402.         d = *data++ ^ doinverse;
  403.         *place = ((d & fg0) | (~d & bg0));
  404.         place[2] = ((d & fg1) | (~d & bg1));
  405.         place += vplanesiz;
  406.  
  407.         /* line 8 */
  408.         d = *data ^ doinverse;
  409.         *place = ((d & fg0) | (~d & bg0));
  410.         place[2] = ((d & fg1) | (~d & bg1));
  411.     }
  412. }
  413.  
  414. static void
  415. paint816m(v, c, place)
  416.     SCREEN *v;
  417.     int c;
  418.     char *place;
  419. {
  420.     char *data;
  421.     char d, doinverse;
  422.     long vplanesiz;
  423.  
  424.     data = chartab[c];
  425.     doinverse = (v->flags & FINVERSE) ? 0xff : 0;
  426.     doinverse ^= bgmask[0];
  427.     vplanesiz = v->planesiz;
  428.  
  429.     if (bgmask[0] == fgmask[0])
  430.       {
  431.         /* fgcol and bgcol are the same -- easy */
  432.         d = (char) bgmask[0];
  433.         *place = d;
  434.         place += vplanesiz;
  435.         *place = d;
  436.         place += vplanesiz;
  437.         *place = d;
  438.         place += vplanesiz;
  439.         *place = d;
  440.         place += vplanesiz;
  441.         *place = d;
  442.         place += vplanesiz;
  443.         *place = d;
  444.         place += vplanesiz;
  445.         *place = d;
  446.         place += vplanesiz;
  447.         *place = d;
  448.         if (v->cheight == 8)
  449.         return;
  450.         place += vplanesiz;
  451.         *place = d;
  452.         place += vplanesiz;
  453.         *place = d;
  454.         place += vplanesiz;
  455.         *place = d;
  456.         place += vplanesiz;
  457.         *place = d;
  458.         place += vplanesiz;
  459.         *place = d;
  460.         place += vplanesiz;
  461.         *place = d;
  462.         place += vplanesiz;
  463.         *place = d;
  464.         place += vplanesiz;
  465.         *place = d;
  466.       }
  467.     else if (!doinverse) {
  468.         /* line 1 */
  469.         d = *data++;
  470.         *place = d;
  471.         place += vplanesiz;
  472.  
  473.         /* line 2 */
  474.         d = *data++;
  475.         *place = d;
  476.         place += vplanesiz;
  477.  
  478.         /* line 3 */
  479.         d = *data++;
  480.         *place = d;
  481.         place += vplanesiz;
  482.  
  483.         /* line 4 */
  484.         d = *data++;
  485.         *place = d;
  486.         place += vplanesiz;
  487.  
  488.         /* line 5 */
  489.         d = *data++;
  490.         *place = d;
  491.         place += vplanesiz;
  492.  
  493.         /* line 6 */
  494.         d = *data++;
  495.         *place = d;
  496.         place += vplanesiz;
  497.  
  498.         /* line 7 */
  499.         d = *data++;
  500.         *place = d;
  501.         place += vplanesiz;
  502.  
  503.         /* line 8 */
  504.         d = *data++;
  505.         *place = d;
  506.  
  507.         if (v->cheight == 8)
  508.             return;
  509.  
  510.         place += vplanesiz;
  511.  
  512.         /* line 9 */
  513.         d = *data++;
  514.         *place = d;
  515.         place += vplanesiz;
  516.  
  517.         /* line 10 */
  518.         d = *data++;
  519.         *place = d;
  520.         place += vplanesiz;
  521.  
  522.         /* line 11 */
  523.         d = *data++;
  524.         *place = d;
  525.         place += vplanesiz;
  526.  
  527.         /* line 12 */
  528.         d = *data++;
  529.         *place = d;
  530.         place += vplanesiz;
  531.  
  532.         /* line 13 */
  533.         d = *data++;
  534.         *place = d;
  535.         place += vplanesiz;
  536.  
  537.         /* line 14 */
  538.         d = *data++;
  539.         *place = d;
  540.         place += vplanesiz;
  541.  
  542.         /* line 15 */
  543.         d = *data++;
  544.         *place = d;
  545.         place += vplanesiz;
  546.  
  547.         /* line 16 */
  548.         d = *data;
  549.         *place = d;
  550.     } else {
  551.         /* line 1 */
  552.         d = ~*data++;
  553.         *place = d;
  554.         place += vplanesiz;
  555.  
  556.         /* line 2 */
  557.         d = ~*data++;
  558.         *place = d;
  559.         place += vplanesiz;
  560.  
  561.         /* line 3 */
  562.         d = ~*data++;
  563.         *place = d;
  564.         place += vplanesiz;
  565.  
  566.         /* line 4 */
  567.         d = ~*data++;
  568.         *place = d;
  569.         place += vplanesiz;
  570.  
  571.         /* line 5 */
  572.         d = ~*data++;
  573.         *place = d;
  574.         place += vplanesiz;
  575.  
  576.         /* line 6 */
  577.         d = ~*data++;
  578.         *place = d;
  579.         place += vplanesiz;
  580.  
  581.         /* line 7 */
  582.         d = ~*data++;
  583.         *place = d;
  584.         place += vplanesiz;
  585.  
  586.         /* line 8 */
  587.         d = ~*data++;
  588.         *place = d;
  589.  
  590.         if (v->cheight == 8)
  591.             return;
  592.  
  593.         place += vplanesiz;
  594.  
  595.         /* line 9 */
  596.         d = ~*data++;
  597.         *place = d;
  598.         place += vplanesiz;
  599.  
  600.         /* line 10 */
  601.         d = ~*data++;
  602.         *place = d;
  603.         place += vplanesiz;
  604.  
  605.         /* line 11 */
  606.         d = ~*data++;
  607.         *place = d;
  608.         place += vplanesiz;
  609.  
  610.         /* line 12 */
  611.         d = ~*data++;
  612.         *place = d;
  613.         place += vplanesiz;
  614.  
  615.         /* line 13 */
  616.         d = ~*data++;
  617.         *place = d;
  618.         place += vplanesiz;
  619.  
  620.         /* line 14 */
  621.         d = ~*data++;
  622.         *place = d;
  623.         place += vplanesiz;
  624.  
  625.         /* line 15 */
  626.         d = ~*data++;
  627.         *place = d;
  628.         place += vplanesiz;
  629.  
  630.         /* line 16 */
  631.         d = ~*data;
  632.         *place = d;
  633.     }
  634. }
  635.  
  636. /*
  637.  * gotoxy (v, x, y): move current cursor address of screen v to (x, y)
  638.  * makes sure that (x, y) will be legal
  639.  */
  640.  
  641. INLINE static void
  642. gotoxy(v, x, y)
  643.     SCREEN *v;
  644.     int x, y;
  645. {
  646.     if (x > v->maxx) x = v->maxx;
  647.     else if (x < 0) x = 0;
  648.     if (y > v->maxy) y = v->maxy;
  649.     else if (y < 0) y = 0;
  650.  
  651.     v->cx = x;
  652.     v->cy = y;
  653.     v->cursaddr = PLACE(v, x, y);
  654. }
  655.  
  656. /*
  657.  * clrline(v, r): clear line r of screen v
  658.  */
  659.  
  660. INLINE static void
  661. clrline(v, r)
  662.     SCREEN *v;
  663.     int r;
  664. {
  665.     int *dst, *m;
  666.     long nwords;
  667.     int i, vplanes;
  668.  
  669.     /* Hey, again the screen might be bigger than 32767 bytes.
  670.        Do another cast... */
  671.     r += r;
  672.     r += r;
  673.     dst = (int *)(base + *(long *)(rowoff+r));
  674.     if (v->bgcol == 0)
  675.       zero((char *)dst, v->linelen);
  676.     else
  677.       {
  678.         /* do it the hard way */
  679.         vplanes = v->planes;
  680.         for (nwords = v->linelen >> 1; nwords > 0; nwords -= vplanes)
  681.           {
  682.         m = bgmask;
  683.         for (i = 0; i < vplanes; i++)
  684.           *dst++ = *m++;
  685.           }
  686.       }
  687. }
  688.     
  689. /*
  690.  * clear(v): clear the whole screen v
  691.  */
  692.  
  693. INLINE static void
  694. clear(v)
  695.     SCREEN *v;
  696. {
  697.     int i, vplanes;
  698.     int *dst, *m;
  699.     long nwords;
  700.  
  701.     if (v->bgcol == 0)
  702.       zero(base, scrnsize);
  703.     else
  704.       {
  705.         /* do it the hard way */
  706.         dst = (int *) base;
  707.         vplanes = v->planes;
  708.         for (nwords = scrnsize >> 1; nwords > 0; nwords -= vplanes)
  709.           {
  710.         m = bgmask;
  711.         for (i = 0; i < vplanes; i++)
  712.           *dst++ = *m++;
  713.           }
  714.       }
  715. }
  716.  
  717. /*
  718.  * clrchar(v, x, y): clear the (x,y) position on screen v
  719.  */
  720.  
  721. INLINE static void
  722. clrchar(v, x, y)
  723.     SCREEN *v;
  724.     int x, y;
  725. {
  726.     int i, j, vplanes;
  727.     char *place;
  728.     int *m;
  729.  
  730.     vplanes = v->planes + v->planes;
  731.  
  732.     place = PLACE(v, x, y);
  733.  
  734.     for (j = v->cheight; j > 0; --j) {
  735.         m = bgmask;
  736.         for (i = 0; i < vplanes; i += 2)
  737.             place[i] = (char) *m++;
  738.         place += v->planesiz;
  739.     }
  740. }
  741.  
  742. /*
  743.  * clrfrom(v, x1, y1, x2, y2): clear screen v from position (x1,y1) to
  744.  * position (x2, y2) inclusive. It is assumed that y2 >= y1.
  745.  */
  746.  
  747. INLINE static void
  748. clrfrom(v, x1, y1, x2, y2)
  749.     SCREEN *v;
  750.     int x1,y1,x2,y2;
  751. {
  752.     int i;
  753.  
  754.     for (i = x1; i <= v->maxx; i++)
  755.         clrchar(v, i, y1);
  756.     if (y2 > y1) {
  757.         for (i = 0; i <= x2; i++)
  758.             clrchar(v, i, y2);
  759.         for (i = y1+1; i < y2; i++)
  760.             clrline(v, i);
  761.     }
  762. }
  763.  
  764. /*
  765.  * scroll a screen in hardware; if we still have hardware scrolling lines left,
  766.  * just move the physical screen base, otherwise copy the screen back to the
  767.  * hardware base and start over
  768.  */
  769. void
  770. hardware_scroll(v)
  771.     SCREEN *v;
  772. {
  773.  
  774.     ++hardline;
  775.     if (hardline < hardscroll) { /* just move the screen */
  776.         base += v->linelen;
  777.     } else {
  778.         hardline = 0;
  779.         quickmove(hardbase, base + v->linelen, scrnsize - v->linelen);
  780.         base = hardbase;
  781.     }
  782.     v->cursaddr = PLACE(v, v->cx, v->cy);
  783.     Setscreen(base, base, -1);
  784. }
  785.  
  786. /*
  787.  * delete_line(v, r): delete line r of screen v. The screen below this
  788.  * line is scrolled up, and the bottom line is cleared.
  789.  */
  790.  
  791. #define scroll(v) delete_line(v, 0)
  792.  
  793. INLINE static void
  794. delete_line(v, r)
  795.     SCREEN *v;
  796.     int r;
  797. {
  798.     long *src, *dst, nbytes;
  799.  
  800.     if (r == 0) {
  801.         if (hardbase) {
  802.             hardware_scroll(v);
  803.             clrline(v, v->maxy);
  804.             return;
  805.         }
  806.         nbytes = scrnsize - v->linelen;
  807.     } else {
  808.         register int i = v->maxy - r;
  809.         i += i;
  810.         i += i;
  811.         nbytes = *(long *)(rowoff+i);
  812.     }
  813.  
  814.     /* Sheeze, how many times do we really have to cast... 
  815.        Erling.    
  816.     */
  817.  
  818.     r += r;
  819.     r += r;
  820.     dst = (long *)(base + *(long *)(rowoff + r));
  821.     src = (long *)( ((long)dst) + v->linelen);
  822.  
  823.     quickmove(dst, src, nbytes);
  824.  
  825. /* clear the last line */
  826.     clrline(v, v->maxy);
  827. }
  828.  
  829. /*
  830.  * insert_line(v, r): scroll all of the screen starting at line r down,
  831.  * and then clear line r.
  832.  */
  833.  
  834. INLINE static void
  835. insert_line(v, r)
  836.     SCREEN *v;
  837.     int r;
  838. {
  839.     long *src, *dst;
  840.     int i, j, linelen;
  841.  
  842.     i = v->maxy - 1;
  843.     i += i;
  844.     i += i;
  845.     j = r+r;
  846.     j += j;
  847.     linelen = v->linelen;
  848.     src = (long *)(base + *(long *)(rowoff + i));
  849.     dst = (long *)((long)src + linelen);
  850.     for (; i >= j ; i -= 4) {
  851.     /* move line i to line i+1 */
  852.         quickmove(dst, src, linelen);
  853.         dst = src;
  854.         src = (long *)((long) src - linelen);
  855.     }
  856.  
  857. /* clear line r */
  858.     clrline(v, r);
  859. }
  860.  
  861. /*
  862.  * special states for handling ESC b x and ESC c x. Note that for now,
  863.  * color is ignored.
  864.  */
  865.  
  866. static void
  867. setbgcol(v, c)
  868.     SCREEN *v;
  869.     int c;
  870. {
  871.     int i;
  872.  
  873.     v->bgcol = c & ((1 << v->planes)-1);
  874.     for (i = 0; i < v->planes; i++)
  875.         bgmask[i] = (v->bgcol & (1 << i)) ? -1 : 0;
  876.     state = normal_putch;
  877. }
  878.  
  879. static void
  880. setfgcol(v, c)
  881.     SCREEN *v;
  882.     int c;
  883. {
  884.     int i;
  885.  
  886.     v->fgcol = c & ((1 << v->planes)-1);
  887.     for (i = 0; i < v->planes; i++)
  888.         fgmask[i] = (v->fgcol & (1 << i)) ? -1 : 0;
  889.     state = normal_putch;
  890. }
  891.  
  892. static void
  893. setcurs(v, c)
  894.     SCREEN *v;
  895.     int c;
  896. {
  897.     c -= ' ';
  898.     if (!c) {
  899.         v->flags &= ~CURS_FLASH;
  900.     } else {
  901.         v->flags |= CURS_FLASH;
  902.         v->period = (unsigned char) c;
  903.     }
  904.     state = normal_putch;
  905. }
  906.  
  907. static void
  908. quote_putch(v, c)
  909.     SCREEN *v;
  910.     int c;
  911. {
  912.     (*vpaint)(v, c, v->cursaddr);
  913.     state = normal_putch;
  914. }
  915.  
  916. /*
  917.  * putesc(v, c): handle the control sequence ESC c
  918.  */
  919.  
  920. static void
  921. putesc(v, c)
  922.     SCREEN *v;
  923.     int c;
  924. {
  925.     int i;
  926.     int cx, cy;
  927.  
  928.     cx = v->cx; cy = v->cy;
  929.  
  930.     switch (c) {
  931.     case 'A':        /* cursor up */
  932.         if (cy) {
  933. moveup:            v->cy = --cy;
  934.             v->cursaddr -= v->linelen;
  935.         }
  936.         break;
  937.     case 'B':        /* cursor down */
  938.         if (cy < v->maxy) {
  939.             v->cy = ++cy;
  940.             v->cursaddr += v->linelen;
  941.         }
  942.         break;
  943.     case 'C':        /* cursor right */
  944.         if (cx < v->maxx) {
  945.             if ((i = v->planes-1) && (cx & 1))
  946.                 v->cursaddr += i + i;
  947.             v->cx = ++cx;
  948.             v->cursaddr++;
  949.         }
  950.         break;
  951.     case 'D':        /* cursor left */
  952.         if (cx) {
  953.             v->cx = --cx;
  954.             v->cursaddr--;
  955.             if ((i = v->planes-1) && (cx & 1))
  956.                 v->cursaddr -= i + i;
  957.         }
  958.         break;
  959.     case 'E':        /* clear home */
  960.         clear(v);
  961.         /* fall through... */
  962.     case 'H':        /* cursor home */
  963.         v->cx = 0; v->cy = 0;
  964.         v->cursaddr = base;
  965.         break;
  966.     case 'I':        /* cursor up, insert line */
  967.         if (cy == 0) {
  968.             insert_line(v, 0);
  969.         }
  970.         else
  971.             goto moveup;
  972.         break;
  973.     case 'J':        /* clear below cursor */
  974.         clrfrom(v, cx, cy, v->maxx, v->maxy);
  975.         break;
  976.     case 'K':        /* clear remainder of line */
  977.         clrfrom(v, cx, cy, v->maxx, cy);
  978.         break;
  979.     case 'L':        /* insert a line */
  980.         v->cx = 0;
  981.         i = cy + cy;
  982.         i += i;
  983.         v->cursaddr = base + *(long *)(rowoff + i);
  984.         insert_line(v, cy);
  985.         break;
  986.     case 'M':        /* delete line */
  987.         v->cx = 0;
  988.         i = cy + cy;
  989.         i += i;
  990.         v->cursaddr = base + *(long *)(rowoff + i);
  991.         delete_line(v, cy);
  992.         break;
  993.     case 'Q':        /* EXTENSION: quote-next-char */
  994.         state = quote_putch;
  995.         return;
  996.     case 'Y':
  997.         state = escy_putch;
  998.         return;        /* YES, this should be 'return' */
  999.  
  1000.     case 'b':
  1001.         state = setfgcol;
  1002.         return;
  1003.     case 'c':
  1004.         state = setbgcol;
  1005.         return;
  1006.     case 'd':        /* clear to cursor position */
  1007.         clrfrom(v, 0, 0, cx, cy);
  1008.         break;
  1009.     case 'e':        /* enable cursor */
  1010.         v->flags |= CURS_ON;
  1011.         v->hidecnt = 1;    /* so --v->hidecnt shows the cursor */
  1012.         break;
  1013.     case 'f':        /* cursor off */
  1014.         v->hidecnt++;
  1015.         v->flags &= ~CURS_ON;
  1016.         break;
  1017.     case 'j':        /* save cursor position */
  1018.         v->savex = v->cx;
  1019.         v->savey = v->cy;
  1020.         break;
  1021.     case 'k':        /* restore saved position */
  1022.         gotoxy(v, v->savex, v->savey);
  1023.         break;
  1024.     case 'l':        /* clear line */
  1025.         v->cx = 0;
  1026.         i = cy + cy;
  1027.         i += i;
  1028.         v->cursaddr = base + *(long *)(rowoff + i);
  1029.         clrline(v, cy);
  1030.         break;
  1031.     case 'o':        /* clear from start of line to cursor */
  1032.         clrfrom(v, 0, cy, cx, cy);
  1033.         break;
  1034.     case 'p':        /* reverse video on */
  1035.         v->flags |= FINVERSE;
  1036.         break;
  1037.     case 'q':        /* reverse video off */
  1038.         v->flags &= ~FINVERSE;
  1039.         break;
  1040.     case 't':        /* EXTENSION: set cursor flash rate */
  1041.         state = setcurs;
  1042.         return;
  1043.     case 'v':        /* wrap on */
  1044.         v->flags |= FWRAP;
  1045.         break;
  1046.     case 'w':
  1047.         v->flags &= ~FWRAP;
  1048.         break;
  1049.     }
  1050.     state = normal_putch;
  1051. }
  1052.  
  1053. /*
  1054.  * escy1_putch(v, c): for when an ESC Y + char has been seen
  1055.  */
  1056. static void
  1057. escy1_putch(v, c)
  1058.     SCREEN *v;
  1059.     int c;
  1060. {
  1061.     gotoxy(v, c - ' ', escy1 - ' ');
  1062.     state = normal_putch;
  1063. }
  1064.  
  1065. /*
  1066.  * escy_putch(v, c): for when an ESC Y has been seen
  1067.  */
  1068. static void
  1069. escy_putch(v, c)
  1070.     SCREEN *v;
  1071.     int c;
  1072. {
  1073.     UNUSED(v);
  1074.     escy1 = c;
  1075.     state = escy1_putch;
  1076. }
  1077.  
  1078. /*
  1079.  * normal_putch(v, c): put character 'c' on screen 'v'. This is the default
  1080.  * for when no escape, etc. is active
  1081.  */
  1082.  
  1083. static void
  1084. normal_putch(v, c)
  1085.     SCREEN *v;
  1086.     int c;
  1087. {
  1088.     register int i;
  1089.  
  1090. /* control characters */
  1091.     if (c < ' ') {
  1092.         switch (c) {
  1093.         case '\r':
  1094. col0:            v->cx = 0;
  1095.             i = v->cy + v->cy;
  1096.             i += i;
  1097.             v->cursaddr = base + *(long *)(rowoff + i);
  1098.             return;
  1099.         case '\n':
  1100.             if (v->cy == v->maxy) {
  1101.                 scroll(v);
  1102.             } else {
  1103.                 v->cy++;
  1104.                 v->cursaddr += v->linelen;
  1105.             }
  1106.             return;
  1107.         case '\b':
  1108.             if (v->cx) {
  1109.                 v->cx--;
  1110.                 v->cursaddr--;
  1111.                 if ((i = v->planes-1) && (v->cx & 1))
  1112.                     v->cursaddr -= i+i;
  1113.             }
  1114.             return;
  1115.         case '\007':        /* BELL */
  1116.             (void)bconout(CONDEV, 7);
  1117.             return;
  1118.         case '\033':        /* ESC */
  1119.             state = putesc;
  1120.             return;
  1121.         case '\t':
  1122.             if (v->cx < v->maxx) {
  1123.             /* this can't be register for an ANSI compiler */
  1124.                 union {
  1125.                     long l;
  1126.                     short i[2];
  1127.                 } j;
  1128.                 j.l = 0;
  1129.                 j.i[1] = 8 - (v->cx & 7);
  1130.                 v->cx += j.i[1];
  1131.                 if (v->cx - v->maxx > 0) {
  1132.                     j.i[1] = v->cx - v->maxx;
  1133.                     v->cx = v->maxx;
  1134.                 }
  1135.                 v->cursaddr += j.l;
  1136.                 if ((i = v->planes-1)) {
  1137.                     if (j.l & 1)
  1138.                         j.i[1]++;
  1139.                     do v->cursaddr += j.l;
  1140.                     while (--i);
  1141.                 }
  1142.             }
  1143.             return;
  1144.         default:
  1145.             return;
  1146.         }
  1147.     }
  1148.  
  1149.     (*vpaint)(v, c, v->cursaddr);
  1150.     v->cx++;
  1151.     if (v->cx > v->maxx) {
  1152.         if (v->flags & FWRAP) {
  1153.             normal_putch(v, '\n');
  1154.             goto col0;
  1155.         } else {
  1156.             v->cx = v->maxx;
  1157.         }
  1158.     } else {
  1159.         v->cursaddr++;
  1160.         if ((i = v->planes-1) && !(v->cx & 1))    /* new word */
  1161.             v->cursaddr += i + i;
  1162.     }
  1163. }
  1164.  
  1165. INLINE static void
  1166. put_ch(v, c)
  1167.     SCREEN *v;
  1168.     int c;
  1169. {
  1170.     (*state)(v, c & 0x00ff);
  1171. }
  1172.  
  1173. static long ARGS_ON_STACK screen_open    P_((FILEPTR *f));
  1174. static long ARGS_ON_STACK screen_read    P_((FILEPTR *f, char *buf, long nbytes));
  1175. static long ARGS_ON_STACK screen_write P_((FILEPTR *f, const char *buf, long nbytes));
  1176. static long ARGS_ON_STACK screen_lseek P_((FILEPTR *f, long where, int whence));
  1177. static long ARGS_ON_STACK screen_ioctl P_((FILEPTR *f, int mode, void *buf));
  1178. static long ARGS_ON_STACK screen_close P_((FILEPTR *f, int pid));
  1179. static long ARGS_ON_STACK screen_select P_((FILEPTR *f, long p, int mode));
  1180. static void ARGS_ON_STACK screen_unselect P_((FILEPTR *f, long p, int mode));
  1181.  
  1182. extern long    ARGS_ON_STACK null_datime    P_((FILEPTR *f, short *time, int rwflag));
  1183.  
  1184. DEVDRV screen_device = {
  1185.     screen_open, screen_write, screen_read, screen_lseek, screen_ioctl,
  1186.     null_datime, screen_close, screen_select, screen_unselect
  1187. };
  1188.  
  1189. static long ARGS_ON_STACK 
  1190. screen_open(f)
  1191.     FILEPTR *f;
  1192. {
  1193.  
  1194.     if (!current) {
  1195.         init();
  1196.     } else
  1197.         return EACCDN;        /* screen in use */
  1198.  
  1199.     f->flags |= O_TTY;
  1200.     return 0;
  1201. }
  1202.  
  1203. static long ARGS_ON_STACK 
  1204. screen_close(f, pid)
  1205.     FILEPTR *f;
  1206.     int pid;
  1207. {
  1208.     UNUSED(pid);
  1209.  
  1210.     if (f->links <= 0) {
  1211.         if (hardbase) {
  1212.             quickmove(oldbase, base, scrnsize);
  1213.             base = oldbase;
  1214.             Setscreen(oldbase, oldbase, -1);
  1215.         }
  1216.         current = 0;
  1217.     }
  1218.     return 0;
  1219. }
  1220.  
  1221. static long ARGS_ON_STACK 
  1222. screen_write(f, buf, bytes)
  1223.     FILEPTR *f; const char *buf; long bytes;
  1224. {
  1225.     SCREEN *v = current;
  1226.     long *r;
  1227.     long ret = 0;
  1228.     int c;
  1229.  
  1230.     UNUSED(f);
  1231.  
  1232.     (void)checkkeys();
  1233.     v->hidecnt++;
  1234.     v->flags |= CURS_UPD;        /* for TOS 1.0 */
  1235.     curs_off(v);
  1236.     r = (long *)buf;
  1237.     while (bytes > 0) {
  1238.         c = (int) *r++;
  1239.         put_ch(v, c);
  1240.         bytes -= 4; ret+= 4;
  1241.     }
  1242.     if (v->hidecnt > 0)
  1243.         --v->hidecnt;
  1244.     else
  1245.         v->hidecnt = 0;
  1246.     curs_on(v);
  1247.     v->flags &= ~CURS_UPD;
  1248.     return ret;
  1249. }
  1250.  
  1251. static long ARGS_ON_STACK 
  1252. screen_read(f, buf, bytes)
  1253.     FILEPTR *f; char *buf; long bytes;
  1254. {
  1255.     long *r, ret = 0;
  1256.  
  1257.     r = (long *)buf;
  1258.  
  1259.     while (bytes > 0) {
  1260.         if ( (f->flags & O_NDELAY) && !bconstat(CONDEV) )
  1261.             break;
  1262.         *r++ = bconin(CONDEV) & 0x7fffffffL;
  1263.         bytes -= 4; ret += 4;
  1264.     }
  1265.     return ret;
  1266. }
  1267.  
  1268. static long ARGS_ON_STACK 
  1269. screen_lseek(f, where, whence)
  1270.     FILEPTR *f;
  1271.     long where;
  1272.     int whence;
  1273. {
  1274. /* terminals always are at position 0 */
  1275.     UNUSED(f); UNUSED(where);
  1276.     UNUSED(whence);
  1277.     return 0;
  1278. }
  1279.  
  1280. static long ARGS_ON_STACK 
  1281. screen_ioctl(f, mode, buf)
  1282.     FILEPTR *f; int mode; void *buf;
  1283. {
  1284.     long *r = (long *)buf;
  1285.     struct winsize *w;
  1286.  
  1287.     UNUSED(f);
  1288.  
  1289.     if (mode == FIONREAD) {
  1290.         if (bconstat(CONDEV))
  1291.             *r = 1;
  1292.         else
  1293.             *r = 0;
  1294.     }
  1295.     else if (mode == FIONWRITE) {
  1296.             *r = 1;
  1297.     }
  1298.     else if (mode == TIOCFLUSH) {
  1299. /* BUG: this should flush the input/output buffers */
  1300.         return 0;
  1301.     }
  1302.     else if (mode == TIOCGWINSZ) {
  1303.         w = (struct winsize *)buf;
  1304.         w->ws_row = current->maxy+1;
  1305.         w->ws_col = current->maxx+1;
  1306.     }
  1307.     else if (mode >= TCURSOFF && mode <= TCURSGRATE) {
  1308.         SCREEN *v = current;
  1309.         switch(mode) {
  1310.         case TCURSOFF:
  1311.             curs_off(v);
  1312.             v->hidecnt++;
  1313.             v->flags &= ~CURS_ON;
  1314.             break;
  1315.         case TCURSON:
  1316.             v->flags |= CURS_ON;
  1317.             v->hidecnt = 0;
  1318.             curs_on(v);
  1319.             break;
  1320.         case TCURSBLINK:
  1321.             curs_off(v);
  1322.             v->flags |= CURS_FLASH;
  1323.             curs_on(v);
  1324.             break;
  1325.         case TCURSSTEADY:
  1326.             curs_off(v);
  1327.             v->flags &= ~CURS_FLASH;
  1328.             curs_on(v);
  1329.             break;
  1330.         case TCURSSRATE:
  1331.             v->period = *((short *)buf);
  1332.             break;
  1333.         case TCURSGRATE:
  1334.             return v->period;
  1335.         }
  1336.     } else
  1337.         return EINVFN;
  1338.  
  1339.     return 0;
  1340. }
  1341.  
  1342. static long ARGS_ON_STACK 
  1343. screen_select(f, p, mode)
  1344.     FILEPTR *f; long p; int mode;
  1345. {
  1346.     struct tty *tty = (struct tty *)f->devinfo;
  1347.     int dev = CONDEV;
  1348.  
  1349.     if (mode == O_RDONLY) {
  1350.         if (bconstat(dev)) {
  1351.             return 1;
  1352.         }
  1353.         if (tty) {
  1354.         /* avoid collisions with other processes */
  1355.             if (!tty->rsel)
  1356.                 tty->rsel = p;
  1357.         }
  1358.         return 0;
  1359.     } else if (mode == O_WRONLY) {
  1360.         return 1;
  1361.     }
  1362.     /* default -- we don't know this mode, return 0 */
  1363.     return 0;
  1364. }
  1365.  
  1366. static void ARGS_ON_STACK 
  1367. screen_unselect(f, p, mode)
  1368.     FILEPTR *f;
  1369.     long p;
  1370.     int mode;
  1371. {
  1372.     struct tty *tty = (struct tty *)f->devinfo;
  1373.  
  1374.     if (tty) {
  1375.         if (mode == O_RDONLY && tty->rsel == p)
  1376.             tty->rsel = 0;
  1377.         else if (mode == O_WRONLY && tty->wsel == p)
  1378.             tty->wsel = 0;
  1379.     }
  1380. }
  1381.  
  1382. #endif /* FASTTEXT */
  1383.